home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 52 / Amiga Format AFCD52 (Issue 136, May 2000).iso / -serious- / programming / other / dopus412-gpl / library / wildcard.c < prev   
C/C++ Source or Header  |  2000-02-28  |  8KB  |  364 lines

  1. /*
  2.  
  3. Directory Opus 4
  4. Original GPL release version 4.12
  5. Copyright 1993-2000 Jonathan Potter
  6.  
  7. This program is free software; you can redistribute it and/or
  8. modify it under the terms of the GNU General Public License
  9. as published by the Free Software Foundation; either version 2
  10. of the License, or (at your option) any later version.
  11.  
  12. This program is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with this program; if not, write to the Free Software
  19. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  20.  
  21. All users of Directory Opus 4 (including versions distributed
  22. under the GPL) are entitled to upgrade to the latest version of
  23. Directory Opus version 5 at a reduced price. Please see
  24. http://www.gpsoft.com.au for more information.
  25.  
  26. The release of Directory Opus 4 under the GPL in NO WAY affects
  27. the existing commercial status of Directory Opus 5.
  28.  
  29. */
  30.  
  31. #include "dopuslib.h"
  32.  
  33. #define upper(c) ((c>='a' && c<='z')?(c-32):c)
  34.  
  35. struct MatchData {
  36.     unsigned char *str,*pat;
  37.     int levels,cas,flags;
  38. };
  39.  
  40. extern __stdargs __saveds DoMatchPattern(unsigned char *,unsigned char *,int);
  41. extern void __stdargs __saveds DoParsePattern(unsigned char *,unsigned char *,int);
  42. extern int WildMatch(struct MatchData *),findendor(struct MatchData *,int);
  43. extern struct DOpusBase *DOpusBase;
  44.  
  45. __stdargs __saveds DoMatchPattern(pat,str,cas)
  46. unsigned char *pat,*str;
  47. int cas;
  48. {
  49.     if (DOSBase->dl_lib.lib_Version>35) {
  50.         int suc,old;
  51.  
  52.         old=DOSBase->dl_Root->rn_Flags&RNF_WILDSTAR;
  53.         DOSBase->dl_Root->rn_Flags|=RNF_WILDSTAR;
  54.         if (cas) suc=(int)MatchPatternNoCase(pat,str);
  55.         else suc=(int)MatchPattern(pat,str);
  56.         if (!old) DOSBase->dl_Root->rn_Flags&=~RNF_WILDSTAR;
  57.         return(suc);
  58.     }
  59.     else {
  60.         struct MatchData mdata;
  61.  
  62.         mdata.str=str;
  63.         mdata.pat=pat;
  64.         mdata.levels=mdata.flags=0;
  65.         mdata.cas=cas;
  66.         return(WildMatch(&mdata));
  67.     }
  68. }
  69.  
  70. void __stdargs __saveds DoParsePattern(pat,patbuf,cas)
  71. unsigned char *pat,*patbuf;
  72. int cas;
  73. {
  74.     if (DOSBase->dl_lib.lib_Version>35) {
  75.         int len,old;
  76.  
  77.         old=DOSBase->dl_Root->rn_Flags&RNF_WILDSTAR;
  78.         DOSBase->dl_Root->rn_Flags|=RNF_WILDSTAR;
  79.         len=(strlen(pat)*2)+2;
  80.         if (cas) ParsePatternNoCase(pat,patbuf,len);
  81.         else ParsePattern(pat,patbuf,len);
  82.         if (!old) DOSBase->dl_Root->rn_Flags&=~RNF_WILDSTAR;
  83.     }
  84.     else {
  85.         int or=0,class=0,rep=0;
  86.  
  87.         while (*pat) {
  88.             switch (*pat) {
  89.                 case '*':
  90.                     if (rep) {
  91.                         *patbuf++=P_REPEND;
  92.                         rep=0;
  93.                     }
  94.                     *patbuf++=P_ANY;
  95.                     break;
  96.                 case '?':
  97.                     if (rep) {
  98.                         *patbuf++=P_REPEND;
  99.                         rep=0;
  100.                     }
  101.                     *patbuf++=P_SINGLE;
  102.                     break;
  103.                 case '(':
  104.                     if (rep) rep=0;
  105.                     *patbuf++=P_ORSTART;
  106.                     ++or;
  107.                     break;
  108.                 case '|':
  109.                     if (rep) rep=0;
  110.                     if (or) *patbuf++=P_ORNEXT;
  111.                     else *patbuf++='|';
  112.                     break;
  113.                 case ')':
  114.                     if (rep) {
  115.                         *patbuf++=P_REPEND;
  116.                         rep=0;
  117.                     }
  118.                     if (or) {
  119.                         *patbuf++=P_OREND;
  120.                         --or;
  121.                     }
  122.                     else *patbuf++=')';
  123.                     break;
  124.                 case '~':
  125.                     if (rep) {
  126.                         *patbuf++=P_REPEND;
  127.                         rep=0;
  128.                     }
  129.                     *patbuf++=P_NOT;
  130.                     break;
  131.                 case '[':
  132.                     if (class) *patbuf++='[';
  133.                     else {
  134.                         *patbuf++=P_CLASS;
  135.                         class=1;
  136.                     }
  137.                     break;
  138.                 case ']':
  139.                     if (class) {
  140.                         *patbuf++=P_CLASS;
  141.                         class=0;
  142.                     }
  143.                     else *patbuf++=']';
  144.                     if (rep) {
  145.                         *patbuf++=P_REPEND;
  146.                         rep=0;
  147.                     }
  148.                     break;
  149.                 case '#':
  150.                     if (*(pat+1)=='?' || *(pat+1)=='*') {
  151.                         *patbuf++=P_ANY;
  152.                         ++pat;
  153.                     }
  154.                     else {
  155.                         *patbuf++=P_REPBEG;
  156.                         rep=1;
  157.                     }
  158.                     break;
  159.                 case '%':
  160.                     break;
  161.                 case '\'':
  162.                     ++pat;
  163.                 default:
  164.                     *patbuf++=(cas)?upper(*pat):*pat;
  165.                     if (rep && !class) {
  166.                         *patbuf++=P_REPEND;
  167.                         rep=0;
  168.                     }
  169.                     break;
  170.             }
  171.             ++pat;
  172.         }
  173.         *patbuf=0;
  174.     }
  175. }
  176.  
  177. WildMatch(mdata)
  178. struct MatchData *mdata;
  179. {
  180.     int last,match,not=0,lnot,other=0,wild=0;
  181.     unsigned char ch,*str,mc,*pat=NULL;
  182.  
  183.     if (!(mdata->flags&2)) {
  184.         for (last=0;;last++) {
  185.             if (mdata->pat[last]>0x7f) {
  186.                 if (mdata->pat[last]!=P_ANY && mdata->pat[last]!=P_NOT &&
  187.                     mdata->pat[last]!=P_SINGLE) other=1;
  188.                 wild=1;
  189.             }
  190.             else if (!mdata->pat[last]) {
  191.                 if (wild) break;
  192.                 if (mdata->cas) return((LStrCmpI((char *)mdata->pat,(char *)mdata->str)==0));
  193.                 return((strcmp((char *)mdata->pat,(char *)mdata->str)==0));
  194.             }
  195.         }
  196.         if (!other) {
  197.             match=1; lnot=0;
  198.             FOREVER {
  199.                 if (*(mdata->pat)==P_NOT) {
  200.                     if (!(*++mdata->pat)) break;
  201.                     not=1-not; lnot=0;
  202.                 }
  203.                 else if (*(mdata->pat)==P_ANY) {
  204.                     if (!(*++mdata->pat)) {
  205.                         if (not) match=1-match;
  206.                         return(match);
  207.                     }
  208.                     pat=mdata->pat; match=lnot=1;
  209.                 }
  210.                 else if (*(mdata->pat)==P_SINGLE) {
  211.                     ++mdata->str;
  212.                     match=1;
  213.                     if (!(*++mdata->pat)) {
  214.                         if (*mdata->str && pat) {
  215.                             mdata->pat=pat;
  216.                             continue;
  217.                         }
  218.                         break;
  219.                     }
  220.                 }
  221.                 else {
  222.                     mc=mdata->cas?upper(*(mdata->str)):*(mdata->str);
  223.                     if (*mdata->str) ++mdata->str;
  224.                     if (*(mdata->pat)!=mc) {
  225.                         match=0;
  226.                         if (!lnot) break;
  227.                         if (pat && *(mdata->str)) {
  228.                             mdata->pat=pat;
  229.                             if (*(mdata->str-1)==*pat) --mdata->str;
  230.                         }
  231.                         else if (!(*++mdata->pat)) break;
  232.                     }
  233.                     else {
  234.                         match=1;
  235.                         if (!(*++mdata->pat)) {
  236.                             if (*mdata->str && pat) {
  237.                                 mdata->pat=pat;
  238.                                 continue;
  239.                             }
  240.                             break;
  241.                         }
  242.                     }
  243.                 }
  244.             }
  245.             if (match && !(*(mdata->str))) return(1-not);
  246.             return(not);
  247.         }
  248.         mdata->flags|=2;
  249.     }
  250.  
  251.     for (;*(mdata->pat);mdata->pat++) {
  252. doswitch:
  253.         switch (*(mdata->pat)) {
  254.             case P_NOT:
  255.                 not=1-not;
  256.                 continue;
  257.             case P_REPBEG:
  258.                 ++mdata->pat;
  259.                 mc=mdata->cas?upper(*(mdata->str)):*(mdata->str);
  260.                 if ((ch=*(mdata->pat))==P_CLASS) {
  261.                     for (last=256,match=0;*(++mdata->pat) && *(mdata->pat)!=P_CLASS;last=*(mdata->pat)) {
  262.                         if (((*mdata->pat)=='-')?(mc<=*(++mdata->pat) &&
  263.                             mc>=last):(mc==*(mdata->pat))) {
  264.                             match=1; ch=*(mdata->pat);
  265.                         }
  266.                     }
  267.                     if (!match) continue;
  268.                 }
  269.                 else if (ch>0x7f) goto doswitch;
  270.                 if (mdata->cas) ch=upper(ch);
  271.                 while (mc==ch) ++mdata->str;
  272.             case P_REPEND:
  273.                 continue;
  274.             case P_SINGLE:
  275.                 if (!(*(mdata->str))) return(not);
  276.                 ++mdata->str;
  277.                 continue;
  278.             case P_ORSTART:
  279.                 str=mdata->str; match=0;
  280.                 FOREVER {
  281.                     ++mdata->pat; mdata->str=str;
  282.                     ++mdata->levels;
  283.                     if (WildMatch(mdata)) {
  284.                         --mdata->levels;
  285.                         match=1;
  286.                         break;
  287.                     }
  288.                     --mdata->levels;
  289.                     findendor(mdata,1);
  290.                     if (*(mdata->pat)!=P_ORNEXT) break;
  291.                 }
  292.                 if (!match) {
  293.                     if (!mdata->levels) return(not);
  294.                     return(0);
  295.                 }
  296.                 findendor(mdata,0);
  297.                 continue;
  298.             case P_ORNEXT:
  299.             case P_OREND:
  300.                 if (mdata->levels) {
  301.                     --mdata->pat;
  302.                     return(1);
  303.                 }
  304.                 continue;
  305.             case P_ANY:
  306.                 match=1;
  307.                 if (*(++mdata->pat)) {
  308.                     pat=mdata->pat;
  309.                     while (!WildMatch(mdata)) {
  310.                         if (!(*(++mdata->str))) {
  311.                             match=0;
  312.                             break;
  313.                         }
  314.                         mdata->pat=pat;
  315.                     }
  316.                 }
  317.                 if (not) return(1-match);
  318.                 return(match);
  319.             case P_CLASS:
  320.                 pat=mdata->pat;
  321.                 if (*(mdata->pat+1)=='~' || *(mdata->pat+1)=='^') {
  322.                     lnot=1;
  323.                     ++mdata->pat;
  324.                 }
  325.                 else lnot=0;
  326.                 mc=mdata->cas?upper(*(mdata->str)):*(mdata->str);
  327.                 for (last=256,match=0;*(++mdata->pat) && *(mdata->pat)!=P_CLASS;last=*(mdata->pat))
  328.                     if (((*mdata->pat)=='-')?(mc<=*(++mdata->pat) &&
  329.                         mc>=last):(mc==*(mdata->pat))) match=1-lnot;
  330.                 if (match==not) {
  331.                     mdata->pat=pat;
  332.                     return(0);
  333.                 }
  334.                 ++mdata->str;
  335.                 continue;
  336.             default:
  337.                 mc=mdata->cas?upper(*(mdata->str)):*(mdata->str);
  338.                 if (mc!=*(mdata->pat)) return(not);
  339.                 ++mdata->str;
  340.                 continue;
  341.         }
  342.     }
  343.     if (!(*(mdata->str))) return(1-not);
  344.     return(not);
  345. }
  346.  
  347. findendor(mdata,a)
  348. struct MatchData *mdata;
  349. int a;
  350. {
  351.     int lev=1;
  352.  
  353.     if (*(mdata->pat)==P_OREND) ++mdata->pat;
  354.     while (*(mdata->pat)) {
  355.         if (*(mdata->pat)==P_ORNEXT && a && lev==1) return(0);
  356.         if (*(mdata->pat)==P_ORSTART) ++lev;
  357.         else if (*(mdata->pat)==P_OREND) {
  358.             --lev;
  359.             if (lev==0) return(0);
  360.         }
  361.         ++mdata->pat;
  362.     }
  363. }
  364.